// 实现异步工作器
#ifndef __M_LOOPER_H__
#define __M_LOOPER_H__

#include "buffer.hpp"
#include <mutex>
#include <thread>
#include <condition_variable>
#include <functional>
#include <memory>

namespace whlog
{
    using Function = std::function<void(Buffer &)>;
    enum class AsyncType
    {
        ASYNC_SAFE,
        ASYNC_UNSAFE
    };

    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Function &cb, AsyncType looper_type = AsyncType::ASYNC_SAFE)
            : _stop(false), _thread(std::thread(&AsyncLooper::threadEntry, this)), _callBack(cb), _looper_type(looper_type)
        {
        }
        ~AsyncLooper() { stop(); }
        void stop()
        {
            _stop = true;
            _cond_con.notify_all(); // 唤醒所有的工作线程
            _thread.join();         // 等待工作线程的退出
        }
        void push(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 当生产缓冲区有足够空间时才进行操作，否则等待
            if (_looper_type == AsyncType::ASYNC_SAFE)
                _cond_pro.wait(lock, [&]()
                               { return _pro_buf.writeAbleSize() >= len; });
            _pro_buf.push(data, len);
            // 唤醒消费者进行数据处理
            _cond_con.notify_one();
        }

    private:
        // 线程入口函数,线程具体执行的操作
        void threadEntry()
        {
            while (1)
            {
                // 1.判断生产缓冲区有没有数据，有的情况下对两个缓冲区进行交换，否则就等待
                {
                    // 限定锁的生命周期
                    std::unique_lock<std::mutex> lock(_mutex);
                    if (_stop == true && _pro_buf.empty())
                        break;
                    _cond_con.wait(lock, [&]()
                                   { return _stop || !_pro_buf.empty(); });
                    _con_buf.swap(_pro_buf);
                    // 2.唤醒生产者
                    _cond_pro.notify_all();
                }
                // 3.对消费缓冲区进行数据处理
                _callBack(_con_buf);
                // 4.处理完毕初始化消费缓冲区
                _con_buf.reset();
            }
        }

    private:
        // 对缓冲区数据进行处理的回调函数，由用户传入
        Function _callBack;

    private:
        AsyncType _looper_type; // 异步日志器的安全标志
        bool _stop;             // 工作区停止标志
        Buffer _pro_buf;        // 生产缓冲区
        Buffer _con_buf;        // 工作缓冲区
        std::mutex _mutex;
        std::condition_variable _cond_pro;
        std::condition_variable _cond_con;
        std::thread _thread; // 异步工作器对应的工作线程
    };
}

#endif